package bankeralgorithm

import (
	r "Ryncler/OperatingSystem-Experiment/pkg/util"
	"fmt"
)

var (
	// 进程数量和资源数量
	ProcessNum, ResourcesNum int
	// 可用资源
	Available []int
	// 最大需求
	Max [][]int
	// 分配
	Allocation [][]int
	// 需求
	Need [][]int
	// 请求
	Request []int
	// 工作
	Work []int
	// 完成
	Finish []bool
	// 进程
	Process = make(map[int]string)
)

// 创建进程，初始化变量
func Create() {
	for i := 0; i < ProcessNum; i++ {
		Process[i] = r.RandomString(4)
	}
	Need = make([][]int, ProcessNum)
	for i := range Need {
		Need[i] = make([]int, ResourcesNum)
	}
	Request = make([]int, ResourcesNum)
	Finish = make([]bool, ProcessNum)
}

// 计算需求
func CalculationNeed() {
	for i := 0; i < ProcessNum; i++ {
		for j := 0; j < ResourcesNum; j++ {
			Need[i][j] = Max[i][j] - Allocation[i][j]
		}
	}
}

// 请求资源
func RequestAvailable(pid int, request []int) bool {
	flagNum := 0
	for j := 0; j < ResourcesNum; j++ {
		// 如果请求资源大于需求，报错
		if request[j] <= Need[pid][j] {
			// 如果请求资源大于可用资源，报错
			if request[j] <= Available[j] {
				flagNum++
			} else {
				fmt.Printf("进程%v申请的%v类资源无法满足该进程本次资源请求\n", Process[pid], j)
			}
		} else {
			fmt.Printf("进程%v申请的%v类资源超出该进程的最大资源请求\n", Process[pid], j)
			return false
		}
	}
	// 如果都满足条件，进行分配
	if flagNum == ResourcesNum {
		for j := 0; j < ResourcesNum; j++ {
			Available[j] -= request[j]
			Allocation[pid][j] += request[j]
			Need[pid][j] -= request[j]
		}
		// 判断系统是否处于安全状态
		return IsSafe()
	} else {
		return false
	}
}

// 是否处于安全状态
func IsSafe() bool {
	Work = Available
	// 初始化完成的进程
	for i := 0; i < len(Process); i++ {
		Finish[i] = false
	}
	i := 0
	for {
		if i == ProcessNum {
			break
		}
		if !Finish[i] {
			flagNum := 0
			for j := 0; j < ResourcesNum; j++ {
				// 如果需求小于等于可用资源
				if Need[i][j] <= Work[j] {
					flagNum++
				}
			}
			// 如果满足条件，归还资源
			if flagNum == ResourcesNum {
				for k := 0; k < ResourcesNum; k++ {
					Work[k] += Allocation[i][k]
				}
				// 记录当前进程为完成
				Finish[i] = true
			} else {
				return false
			}
		} else {
			i++
		}
	}
	return true
}
